package com.tiyende.kash.loop.request

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import com.lib.common.http.OkHttp
import com.lib.common.http.cache.CacheEntity
import com.lib.common.http.cache.CacheMode
import com.lib.common.http.callback.StringCallback
import com.lib.common.http.interceptor.HttpLoggingInterceptor
import com.lib.common.http.model.HttpHeaders
import com.lib.common.http.model.Progress
import com.lib.common.http.model.Response
import com.lib.common.http.request.base.Request
import com.lib.common.http.utils.IOUtils
import com.tiyende.kash.loop.BuildConfig
import com.tiyende.kash.loop.TiyendeApp
import com.tiyende.kash.loop.configs.TiyendeApiUrl
import com.tiyende.kash.loop.configs.TiyendeApiUrl.addCommonParams
import com.tiyende.kash.loop.configs.TiyendeConfigs
import com.tiyende.kash.loop.event.TiyendeEventData
import com.tiyende.kash.loop.utils.aes.TiyendeAesUtil
import com.tiyende.kash.loop.utils.log.JsonFormat
import com.tiyende.kash.loop.utils.log.TiyendeLogger
import com.tiyende.kash.loop.utils.track.TrackPointManager
import okhttp3.OkHttpClient
import org.json.JSONObject
import java.io.File
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.nio.charset.Charset
import java.util.concurrent.TimeUnit
import java.util.logging.Level
import javax.net.ssl.SSLHandshakeException

/**
 * HttpLoader
 * @Author wwdeng
 * @CreateTime: 2024/11/20 17:38
 * @Annotation：网络请求
 */
class HttpLoader: IHttpLoader {
    private var httpTag: Any? = null

    init {
        val builder = OkHttpClient.Builder()
        //log相关
        val loggingInterceptor = HttpLoggingInterceptor(TiyendeConfigs.TIYENDE_APPNAME)
        var level = HttpLoggingInterceptor.Level.NONE
        if (BuildConfig.isDebug) {
            level = HttpLoggingInterceptor.Level.BODY
        }
        loggingInterceptor.setPrintLevel(level) //log打印级别，决定了log显示的详细程度
        loggingInterceptor.setColorLevel(Level.INFO) //log颜色级别，决定了log在控制台显示的颜色
        builder.addInterceptor(loggingInterceptor) //添加OkGo默认debug日志
        //第三方的开源库，使用通知显示当前请求的log，不过在做文件下载的时候，这个库好像有问题，对文件判断不准确

        //超时时间设置
        val timeoutMs = if (BuildConfig.isDebug) OkHttp.DEFAULT_MILLISECONDS else 30000L
        builder.readTimeout(timeoutMs, TimeUnit.MILLISECONDS) //全局的读取超时时间
        builder.writeTimeout(timeoutMs, TimeUnit.MILLISECONDS) //全局的写入超时时间
        builder.connectTimeout(15000, TimeUnit.MILLISECONDS) //全局的连接超时时间

        // 其他统一的配置
        // 详细说明看GitHub文档：https://github.com/jeasonlzy/
        OkHttp.getInstance().init(TiyendeApp.app) //必须调用初始化
            .setOkHttpClient(builder.build()) //建议设置OkHttpClient，不设置会使用默认的
            .setCacheMode(CacheMode.NO_CACHE) //全局统一缓存模式，默认不使用缓存，可以不传
            .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE) //全局统一缓存时间，默认永不过期，可以不传
            .setRetryCount(3) //全局统一超时重连次数，默认为三次，那么最差的情况会请求4次(一次原始请求，三次重连请求)，不需要可以设置为0

        //添加通用请求头
        val httpHeaders = HttpHeaders()
        httpHeaders.put("appid", TiyendeConfigs.TIYENDE_APPNAME)
        httpHeaders.put("product", TiyendeConfigs.TIYENDE_APPNAME)
        OkHttp.getInstance().addCommonHeaders(httpHeaders)
    }

    /**
     * post 请求
     */
    override fun post(url: String, params: JSONObject,callback: IHttpCallback) {
        val requestId = NetworkRequestManager.RetryRequest.generateRequestId()
        // 创建包装的回调
        val managedCallback = object : IHttpCallback {
            override fun onRequestSuccess(data: JSONObject) {
                callback.onRequestSuccess(data)
            }

            override fun onRequestError(errorObj: JSONObject) {
                TiyendeApp.app.publisher.publish(TiyendeEventData(TiyendeEventData.TYPE.TIYENDE_REQUEST_ERROR))
                val errorCode = errorObj.optInt("errorCode", -1)
                val errorMsg = errorObj.optString("errorMsg", "Network request failed")

                // 创建重试请求数据
                val retryRequest = NetworkRequestManager.RetryRequest(
                    requestId = requestId,
                    requestType = "POST",
                    url = url,
                    params = params,
                    originalCallback = callback
                )
                // 交给网络错误管理器处理
                NetworkRequestManager.handleNetworkError(errorCode, errorMsg, retryRequest)

                // 同时回调给原始callback
                callback.onRequestError(errorObj)
            }

            override fun onRequestFinish() {
                callback.onRequestFinish()
            }
        }

        // 执行原始请求
        executePost(url, params, managedCallback)
    }

    /**
     * 执行实际的POST请求
     */
    private fun executePost(url: String, params: JSONObject, callback: IHttpCallback) {
        // 网络检查
        if (!isNetworkAvailable()) {
            callback.onRequestError(createErrorObj(HttpErrorCode.NO_NETWORK, "Network unavailable"))
            return
        }
        val aesParams = try {
            TiyendeAesUtil.encryptDefault(params.toString())
        } catch (e: Exception) {
            TiyendeLogger.e("Parameter encryption failed: ${e.message}")
            callback.onRequestError(createErrorObj(HttpErrorCode.PROCESS_ERROR, "Request parameter processing failed"))
            return
        }

        logRequest(url, params, aesParams)

        OkHttp.post<String>(url)
            .tag(httpTag)
            .upString(aesParams)
            .retryCount(2)
            .execute(createStringCallback(url, params, callback))
    }

    /**
     * 重试POST请求
     */
    private fun retryPost(url: String, params: JSONObject, callback: IHttpCallback) {
        TiyendeLogger.i("Retry request: $url")
        executePost(url, params, callback)
    }

    /**
     * 文件上传
     */
    override fun upload(filePath: String, callback: IHttpCallback) {
        val requestId = NetworkRequestManager.RetryRequest.generateRequestId()

        val managedCallback = object : IHttpCallback {
            override fun onRequestSuccess(data: JSONObject) {
                callback.onRequestSuccess(data)
            }

            override fun onRequestError(errorObj: JSONObject) {
                TiyendeApp.app.publisher.publish(TiyendeEventData(TiyendeEventData.TYPE.TIYENDE_REQUEST_ERROR))
                val errorCode = errorObj.optInt("errorCode", -1)
                val errorMsg = errorObj.optString("errorMsg", "Image upload failed")

                val retryRequest = NetworkRequestManager.RetryRequest(
                    requestId = requestId,
                    requestType = "UPLOAD",
                    url = TiyendeApiUrl.getTiyendeHttpUrl(true),
                    params = filePath,
                    originalCallback = callback
                )

                NetworkRequestManager.handleNetworkError(errorCode, errorMsg, retryRequest)
                callback.onRequestError(errorObj)
            }

            override fun onRequestFinish() {
                callback.onRequestFinish()
            }
        }

        executeUpload(filePath, managedCallback)
    }

    /**
     * 执行实际的文件上传
     */
    private fun executeUpload(filePath: String, callback: IHttpCallback) {
        if (filePath.isEmpty()) {
            callback.onRequestError(createErrorObj(HttpErrorCode.PROCESS_ERROR, "file path cannot be empty"))
            return
        }

        val file = File(filePath)
        if (!file.exists()) {
            callback.onRequestError(createErrorObj(HttpErrorCode.PROCESS_ERROR, "File does not exist"))
            return
        }

        // 网络检查
        if (!isNetworkAvailable()) {
            callback.onRequestError(createErrorObj(HttpErrorCode.NO_NETWORK, "Network unavailable"))
            return
        }

        val httpUrl = TiyendeApiUrl.getTiyendeHttpUrl(true)
        OkHttp.post<String>(httpUrl) // 请求方式和请求url
            .tag(httpTag) // 请求的 tag, 主要用于取消对应的请求
            .params("image", file)   //这种方式为一个key，对应一个文件
            .isMultipart(true)
            .retryCount(1) // 文件上传减少重试次数
            .execute(createUploadCallback(httpUrl, filePath, callback))
    }

    /**
     * 重试文件上传
     */
    private fun retryUpload(filePath: String, callback: IHttpCallback) {
        TiyendeLogger.i("Retry file upload: $filePath")
        executeUpload(filePath, callback)
    }


    /**
     * 提交埋点
     */
    override fun postPoint(url: String, params: JSONObject, callback: IHttpCallback) {
        post(url, params = params.addCommonParams(), callback = callback)
    }

    /**
     * 添加打点事件
     */
    override fun addPoint(eventName: String, remark: String?, callback: IHttpCallback) {
        TiyendeLogger.e(">>>>>>>>>>>>>>eventName:$eventName,remark:$remark")
        val eventType = eventName.uppercase()//转大写
        if (remark != null){
            TrackPointManager.getInstance().track(eventType,remark)
        } else {
            TrackPointManager.getInstance().track(eventType,"")
        }
    }

    private fun createStringCallback(url: String, params: JSONObject, callback: IHttpCallback): StringCallback {
        return object : StringCallback() {
            override fun onSuccess(response: Response<String>) {
                handleSuccessResponse(url, params, response, callback)
            }

            override fun onError(response: Response<String>) {
                handleErrorResponse(response, callback)
            }

            override fun onFinish() {
                callback.onRequestFinish()
            }
        }
    }

    private fun handleSuccessResponse(url: String, params: JSONObject, response: Response<String>, callback: IHttpCallback) {
        try {
            val body = response.body()
            if (response.code() != 200 || body.isNullOrEmpty()) {
                val errorMsg = HttpErrorCode.getMessage(response.code())
                callback.onRequestError(createErrorObj(response.code(), errorMsg))
                return
            }

            val result = TiyendeAesUtil.decryptDefault(body)
            if (result.isNotEmpty()) {
                logResponseSuccess(url, params, result)
                val data = JSONObject(result)
                callback.onRequestSuccess(data)
            } else {
                handleDecryptError(callback, result)
            }
        } catch (e: Exception) {
            TiyendeLogger.e("Response to handling exceptions: ${e.message}")
            handleException(callback, e, "Response to data processing exceptions")
        }
    }

    private fun handleErrorResponse(response: Response<String>, callback: IHttpCallback) {
        TiyendeLogger.e("Network request error: ${response.exception?.message}")

        val exception = response.exception
        if (exception != null) {
            handleNetworkException(callback, exception)
        } else {
            handleServerError(response, callback)
        }
    }

    private fun handleServerError(response: Response<String>, callback: IHttpCallback) {
        try {
            val responseBody = response.rawResponse.body
            val bytes = IOUtils.toByteArray(responseBody?.byteStream() ?: return)
            val body = String(bytes, Charset.forName("UTF-8"))
            TiyendeLogger.e("Server error response: $body")

            val errorObj = try {
                JSONObject(body).apply {
                    put("errorCode", optString("code", "-1"))
                    put("errorMsg", optString("msg", "Server Error"))
                }
            } catch (e: Exception) {
                createErrorObj(response.code(), HttpErrorCode.getMessage(response.code()))
            }
            callback.onRequestError(errorObj)
        } catch (e: Exception) {
            callback.onRequestError(createErrorObj(response.code(), response.message()))
        }
    }

    /**
     * 创建文件上传回调
     */
    private fun createUploadCallback(url: String, filePath: String, callback: IHttpCallback): StringCallback {
        return object : StringCallback() {
            override fun onStart(request: Request<String, out Request<Any, Request<*, *>>>?) {
                super.onStart(request)
                TiyendeLogger.e("upload started: $filePath")
            }

            override fun onSuccess(response: Response<String>) {
                TiyendeLogger.e("upload success: ${response.body()}")
                handleUploadSuccessResponse(url, filePath, response, callback)
            }

            override fun onError(response: Response<String>) {
                TiyendeLogger.e("upload failed: ${response.exception?.message}")
                handleUploadErrorResponse(response, callback)
            }

            override fun uploadProgress(progress: Progress) {
                TiyendeLogger.e("upload progress: ${progress.currentSize}/${progress.totalSize} (${progress.fraction})")
                // 可以通过callback传递进度信息，如果需要的话
                // callback.onUploadProgress(progress.fraction, progress.currentSize, progress.totalSize)
            }

            override fun onFinish() {
                TiyendeLogger.e("upload completed")
                callback.onRequestFinish()
            }
        }
    }

    /**
     * 处理文件上传成功响应
     */
    private fun handleUploadSuccessResponse(url: String, filePath: String, response: Response<String>, callback: IHttpCallback) {
        try {
            val body = response.body()
            if (response.code() != 200 || body.isNullOrEmpty()) {
                val errorMsg = HttpErrorCode.getMessage(response.code())
                callback.onRequestError(createErrorObj(response.code(), errorMsg))
                return
            }

            // 文件上传响应通常不需要解密，直接解析JSON
            val data = JSONObject(body)
            when (data.optInt("code")) {
                0 -> { // 成功
                    val obj = data.optJSONObject("obj")
                    obj?.let {
                        val imgUrl = it.optString("url")
                        // 可以在这里添加文件上传成功的特定处理
                        val result = JSONObject().apply {
                            put("filePath", filePath)
                            put("imageUrl", imgUrl)
                            put("rawResponse", data) // 保留原始响应数据
                        }
                        callback.onRequestSuccess(result)
                    } ?: run {
                        callback.onRequestSuccess(data) // 如果没有obj，返回原始数据
                    }
                }
                else -> {
                    val msg = data.optString("msg", "Upload failed")
                    val errorObj = createErrorObj(data.optInt("code", -1), msg)
                    callback.onRequestError(errorObj)
                }
            }
        } catch (e: Exception) {
            TiyendeLogger.e("upload response handling exception: ${e.message}")
            handleException(callback, e, "upload data processing exception")
        }
    }

    /**
     * 处理文件上传错误响应
     */
    private fun handleUploadErrorResponse(response: Response<String>, callback: IHttpCallback) {
        TiyendeLogger.e("upload network error: ${response.exception?.message}")

        val exception = response.exception
        if (exception != null) {
            handleNetworkException(callback, exception)
        } else {
            handleUploadServerError(response, callback)
        }
    }

    /**
     * 处理文件上传服务器错误
     */
    private fun handleUploadServerError(response: Response<String>, callback: IHttpCallback) {
        try {
            val responseBody = response.rawResponse.body
            val bytes = IOUtils.toByteArray(responseBody?.byteStream() ?: return)
            val body = String(bytes, Charset.forName("UTF-8"))
            TiyendeLogger.e("upload server error: $body")

            val errorObj = try {
                val json = JSONObject(body)
                createErrorObj(json.optInt("code", response.code()), json.optString("msg", "Upload failed"))
            } catch (e: Exception) {
                createErrorObj(response.code(), HttpErrorCode.getMessage(response.code()))
            }
            callback.onRequestError(errorObj)
        } catch (e: Exception) {
            callback.onRequestError(createErrorObj(response.code(), response.message()))
        }
    }

    // 创建错误对象
    private fun createErrorObj(errorCode: Int, errorMsg: String): JSONObject {
        return JSONObject().apply {
            put("errorCode", errorCode)
            put("errorMsg", errorMsg)
        }
    }

    // 请求日志
    private fun logRequest(url: String, params: JSONObject, aesParams: String) {
        TiyendeLogger.e("HttpUrl: $url")
        TiyendeLogger.e("HttpParams: $params")
        TiyendeLogger.e("HttpParams AES: $aesParams")
    }

    private fun logResponseSuccess(url: String, params: JSONObject, result: String) {
        Thread {
            TiyendeLogger.i(
                "\nhttpUrl: $url \n" +
                        "path: ${params.optString("path")} \n" +
                        "result: ${JsonFormat.format(result)}"
            )
        }.start()
    }

    //网络状态检查
    private fun isNetworkAvailable(): Boolean {
        return try {
            val connectivityManager = TiyendeApp.app.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
            val network = connectivityManager?.activeNetwork
            val capabilities = connectivityManager?.getNetworkCapabilities(network)
            capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true
        } catch (e: Exception) {
            TiyendeLogger.e("Network check abnormal: ${e.message}")
            false
        }
    }

    // 处理网络层异常
    private fun handleNetworkException(callback: IHttpCallback, exception: Throwable) {
        val errorObj = JSONObject()
        when (exception) {
            is SocketTimeoutException -> {
                errorObj.put("errorCode", HttpErrorCode.TIMEOUT)
                errorObj.put("errorMsg", "Network connection timeout, please check the network and try again")//网络连接超时，请检查网络后重试
            }
            is ConnectException -> {
                errorObj.put("errorCode", HttpErrorCode.CONNECT_FAILED)
                errorObj.put("errorMsg", "Network connection failed, please check network settings“")//网络连接失败，请检查网络设置"
            }
            is UnknownHostException -> {
                errorObj.put("errorCode", HttpErrorCode.NETWORK_UNAVAILABLE)
                errorObj.put("errorMsg", "The network is unavailable, please check the network connection")//网络不可用，请检查网络连接
            }
            is SSLHandshakeException -> {
                errorObj.put("errorCode", HttpErrorCode.SSL_ERROR)
                errorObj.put("errorMsg", "Security certificate verification failed")//安全证书验证失败
            }
            else -> {
                errorObj.put("errorCode", HttpErrorCode.UNKNOWN_ERROR)
                errorObj.put("errorMsg", "Network error: ${exception.message}")//网络异常
            }
        }

        TiyendeLogger.e("Network error: ${exception.javaClass.simpleName} - ${exception.message}")
        callback.onRequestError(errorObj)
    }

    // 处理加解密异常
    private fun handleDecryptError(callback: IHttpCallback, result: String) {
        val errorObj = JSONObject()
        errorObj.put("errorCode", HttpErrorCode.DECRYPT_ERROR)
        errorObj.put("errorMsg", "Data parsing failed")
        TiyendeLogger.e("Decryption failed, original data: $result")
        callback.onRequestError(errorObj)
    }

    // 通用异常处理
    private fun handleException(callback: IHttpCallback, e: Exception, defaultMsg: String) {
        val errorObj = JSONObject()
        errorObj.put("errorCode", HttpErrorCode.PROCESS_ERROR)
        errorObj.put("errorMsg", "$defaultMsg: ${e.message}")
        callback.onRequestError(errorObj)
    }

    /**
     * 设置请求tag
     */
    override fun setTag(tag: Any) {
        this.httpTag = tag
    }

    /**
     * 取消请求
     */
    override fun cancelTag(tag: Any) {
//        OkHttp.getInstance().cancelTag(tag)
    }
}